package btree;

import java.io.IOException;

import javax.xml.bind.annotation.XmlElementDecl.GLOBAL;

import diskmgr.FileEntryNotFoundException;
import diskmgr.Page;
import global.PageId;
import global.RID;
import global.SystemDefs;
import heap.HFPage;
import heap.InvalidSlotNumberException;

public class BTreeFile1
{

	private BTHeaderPage header;
	private PageId headerID;

	public BTHeaderPage getHeaderPage()
	{
		return header;
	}

	public BTreeFile1(String fileName) throws FileEntryNotFoundException
	{
		try
		{
			PageId pageno = SystemDefs.JavabaseDB.get_file_entry(fileName);
			if (pageno == null)
			{
				throw new FileEntryNotFoundException(null,
						"btree.BTreeFile(String fileName): file entry not found");
			} else
			{
				headerID = pageno;
				header = new BTHeaderPage(headerID);
			}
		} catch (Exception e)
		{
			throw new FileEntryNotFoundException(e,
					"btree.BTreeFile(String fileName): file entry not found");
		}
	}

	public BTreeFile1(String filename, int keytype, int keysize,
			int delete_fashion)
	{
		try
		{
			PageId pageno = SystemDefs.JavabaseDB.get_file_entry(filename);
			if (pageno == null)
			{
				try
				{
					header = new BTHeaderPage();
					headerID = header.getCurPage();
					// add the new file entry
					SystemDefs.JavabaseDB.add_file_entry(filename, headerID);
					header.set_keyType((short) keytype);
					header.set_deleteFashion(delete_fashion);
					header.set_maxKeySize(keysize);
					header.set_rootId(new BTLeafPage(keytype).getCurPage());
				} catch (Exception e)
				{

					e.printStackTrace();
				}
			} else
			{
				headerID = pageno;
				header = new BTHeaderPage(headerID);
			}
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	public void close()
	{
		try
		{
			SystemDefs.JavabaseBM.unpinPage(headerID, true);
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	public BTFileScan new_scan(KeyClass lo_key, KeyClass hi_key)
	{
		BTFileScan scan = new BTFileScan();
		scan.setLow_key(lo_key);
		scan.setHigh_key(hi_key);

		return scan;
	}

	public boolean Delete(KeyClass key, RID rid) throws DeleteRecException, BTreeFileException
	{
		KeyDataEntry kde = new KeyDataEntry(key, rid);
		BTLeafPage leafPage = search(key);
		try
		{
			return leafPage.delEntry(kde);
		} catch (Exception e)
		{
			throw new DeleteRecException(e, "BtreeFile.Delete(): delete failed");
		}
	}

	public void destroyFile()
	{

	}

	// ------------------------------------------------------------------------------------------//

	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	public BTLeafPage search(KeyClass key) throws BTreeFileException
	{
		BTSortedPage root;
		try
		{
			// make a new BTSortedPage Object
		    root = new BTSortedPage(header.get_keyType());
			Page tempPage = new Page();
			// pin the next level Page
			SystemDefs.JavabaseBM.pinPage(header.get_rootId(), tempPage, false);
			root.setpage(tempPage.getpage());
			root.dumpPage();
			SystemDefs.JavabaseBM.unpinPage(header.get_rootId(),true);
		} catch (Exception e)
		{
			throw new BTreeFileException("btree.BTreeFile.tree_search(): couldn't pin/unpin next level page");
		}
		return tree_search(root , key);

	}

	private BTLeafPage tree_search(BTSortedPage currentPage , KeyClass key) throws BTreeFileException 
	{
		boolean isLeafPage = false;
		try
		{
			isLeafPage = (currentPage.getType() == NodeType.LEAF) ;
		} catch (Exception e)
		{
			throw new BTreeFileException("btree.BTreeFile.tree_search(): couldn't get Page Type");
		}
		
		// Check if Current Page is a leaf page
		if(isLeafPage) // it's a leaf page
		{
			BTLeafPage requiredPage ;
		// pin the required page
		try
		{
			requiredPage = new BTLeafPage(header.get_keyType()); 
			Page tempPage = new Page();
			SystemDefs.JavabaseBM.pinPage(currentPage.getCurPage(), tempPage, false);
			requiredPage.setpage(tempPage.getpage());
			requiredPage.dumpPage();
		}
		catch (Exception e) 
		{
		throw new BTreeFileException("btree.BTreeFile.tree_search(): couldn't pin the required page");
		}
		return requiredPage;
		}
		
		else // it's an index page
		{
			BTIndexPage currentIndexPage = null ;
			try
			{
			currentIndexPage = new BTIndexPage(currentPage, header.get_keyType());
			currentIndexPage.dumpPage();
			}
			catch (Exception e) 
			{
			throw new BTreeFileException("btree.BTreeFile.tree_search(): couldn't dump the Index page");
			}
			RID currentRecordId = new RID();
			KeyDataEntry firstKey ;
			
			
			// get the first Key from the index page
			try
			{
			firstKey = currentIndexPage.getFirst(currentRecordId);
			} catch (Exception e)
			{
				throw new BTreeFileException("btree.BTreeFile.tree_search(): couldn't get first keyDataEntry");
			} 
			
			// compare the given key to the first key in the page
			int comparison = 0;
			try
			{
				comparison = BT.keyCompare(key, firstKey.key) ;
			}
			catch (Exception e)
			{
				throw new BTreeFileException("btree.BTreeFile.tree_search(): key comparison missmatch");
			}
			BTSortedPage nextLevelPage ;
			if(comparison<0)  // the given key is less than the first key in the index page
			{
				try
				{
					// make a new BTSortedPage Object
				    nextLevelPage = new BTSortedPage(header.get_keyType());
					Page tempPage = new Page();
					// pin the next level Page
					SystemDefs.JavabaseBM.pinPage(currentIndexPage.getLeftLink(), tempPage, false);
					nextLevelPage.setpage(tempPage.getpage());
					nextLevelPage.dumpPage();
					SystemDefs.JavabaseBM.unpinPage(currentIndexPage.getLeftLink(),true);
				} catch (Exception e)
				{
					throw new BTreeFileException("btree.BTreeFile.tree_search(): couldn't pin/unpin next level page");
				}
				// recursive call to the next level of index pages
				return tree_search(nextLevelPage, key);
			}
			else // the given key is not less than the first key in the index page
			{
				KeyDataEntry key1 ;
				KeyDataEntry key2 ;
				
				
				try
				{
					key1 = currentIndexPage.getNext(currentRecordId) ;
					key2 = currentIndexPage.getNext(currentRecordId);
				while(key2!=null && (BT.keyCompare(key, key2.key)<0))
				{
					key1=key2;
					key2=currentIndexPage.getNext(currentRecordId);
				}
				}
				catch (Exception e) 
				{
					throw new BTreeFileException("btree.BTreeFile.tree_search(): error finding the next level page");
				}
				try
				{
					// make a new BTSortedPage Object
				    nextLevelPage = new BTSortedPage(header.get_keyType());
					Page tempPage = new Page();
					// pin the next level Page
					SystemDefs.JavabaseBM.pinPage(((IndexData)key1.data).getData(), tempPage, false);
					nextLevelPage.setpage(tempPage.getpage());
					nextLevelPage.dumpPage();
					SystemDefs.JavabaseBM.unpinPage(((IndexData)key1.data).getData(),true);
				} catch (Exception e)
				{
					throw new BTreeFileException("btree.BTreeFile.tree_search(): couldn't pin/unpin next level page");
				}
				// recursive call to the next level of index pages
				return tree_search(nextLevelPage, key);
			}
		}
	}

	
	
	
	
	
	
	
	
	
	
	
	
	
	
	

	public void insert(KeyClass key, RID rid)
	{
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}
